#include "tinyengine/inner_bmpfont.hpp"

InnerBmpFont::InnerBmpFont() {
    saveChar('0',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,0,0,0,
         0,1,0,0,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,0,0,1,0,0,
         0,0,1,1,1,0,0,0});
    saveChar('1',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,1,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         1,1,1,1,1,1,0,0});
    saveChar('2',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         0,0,0,0,1,1,1,0,
         0,0,1,1,1,1,0,0,
         0,1,1,1,1,0,0,0,
         1,1,1,0,0,0,0,0,
         1,1,1,1,1,1,1,0});
    saveChar('3',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,1,1,0,
         0,0,0,0,1,1,0,0,
         0,0,0,1,1,0,0,0,
         0,0,1,1,1,1,0,0,
         0,0,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('4',
        {0,0,0,0,0,0,0,0,
         0,0,0,1,1,1,0,0,
         0,0,1,1,1,1,0,0,
         0,1,1,0,1,1,0,0,
         1,1,0,0,1,1,0,0,
         1,1,1,1,1,1,1,0,
         0,0,0,0,1,1,0,0,
         0,0,0,0,1,1,0,0});
    saveChar('5',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('6',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,1,0,0,
         0,1,1,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('7',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,1,0,
         1,1,0,0,0,1,1,0,
         0,0,0,0,1,1,0,0,
         0,0,0,1,1,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0});
    saveChar('8',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,0,0,0,
         1,1,0,0,0,1,0,0,
         1,1,1,0,0,1,0,0,
         0,1,1,1,1,0,0,0,
         1,0,0,1,1,1,1,0,
         1,0,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('9',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,1,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,1,1,0,0,
         0,1,1,1,1,0,0,0});

    saveChar('A',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,0,0,0,
         0,1,1,0,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
        });
    saveChar('B',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,1,1,1,0,0});
    saveChar('C',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,1,0,0,
         0,1,1,0,0,1,1,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         0,1,1,0,0,1,1,0,
         0,0,1,1,1,1,0,0});
    saveChar('D',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,0,0,0,
         1,1,0,0,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,1,1,0,0,
         1,1,1,1,1,0,0,0});
    saveChar('E',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,1,1,0});
    saveChar('F',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,1,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0});
    saveChar('G',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,1,1,0,
         0,1,1,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,1,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,0,0,1,1,0,
         0,0,1,1,1,1,1,0});
    saveChar('H',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0});
    saveChar('I',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         1,1,1,1,1,1,0,0});
    saveChar('J',
        {0,0,0,0,0,0,0,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('K',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,1,1,0,0,
         1,1,0,1,1,0,0,0,
         1,1,1,1,0,0,0,0,
         1,1,1,1,1,0,0,0,
         1,1,0,1,1,1,0,0,
         1,1,0,0,1,1,1,0});
    saveChar('L',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0});
    saveChar('M',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,1,0,1,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,0,1,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0});
    saveChar('N',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,1,0,0,1,1,0,
         1,1,1,1,0,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,0,1,1,1,1,0,
         1,1,0,0,1,1,1,0,
         1,1,0,0,0,1,1,0});
    saveChar('O',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('P',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,0,0,0,
         1,1,0,0,0,0,0,0});
    saveChar('Q',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,1,1,1,1,0,
         1,1,0,0,1,1,0,0,
         0,1,1,1,1,0,1,0});
    saveChar('R',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,1,1,1,0,
         1,1,1,1,1,0,0,0,
         1,1,0,1,1,1,0,0,
         1,1,0,0,1,1,1,0});
    saveChar('S',
        {0,0,0,0,0,0,0,0,
         0,1,1,1,1,0,0,0,
         1,1,0,0,1,1,0,0,
         1,1,0,0,0,0,0,0,
         0,1,1,1,1,1,0,0,
         0,0,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('T',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0});
    saveChar('U',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         0,1,1,1,1,1,0,0});
    saveChar('V',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,1,0,1,1,1,0,
         0,1,1,1,1,1,0,0,
         0,0,1,1,1,0,0,0,
         0,0,0,1,0,0,0,0});
    saveChar('W',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,0,0,0,1,1,0,
         1,1,0,1,0,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,1,1,1,1,1,0,
         1,1,1,0,1,1,1,0,
         1,1,0,0,0,1,1,0});
    saveChar('X',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,0,1,1,0,
         1,1,1,0,1,1,1,0,
         0,1,1,1,1,1,0,0,
         0,0,1,1,1,0,0,0,
         0,1,1,1,1,1,0,0,
         1,1,1,0,1,1,1,0,
         1,1,0,0,0,1,1,0});
    saveChar('Y',
        {0,0,0,0,0,0,0,0,
         1,1,0,0,1,1,0,0,
         1,1,0,0,1,1,0,0,
         1,1,0,0,1,1,0,0,
         0,1,1,1,1,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0});
    saveChar('Z',
        {0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,1,0,
         0,0,0,0,1,1,1,0,
         0,0,0,1,1,1,0,0,
         0,0,1,1,1,0,0,0,
         0,1,1,1,0,0,0,0,
         1,1,1,0,0,0,0,0,
         1,1,1,1,1,1,1,0});
    saveChar(':',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,1,0,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,1,1,0,0,0,0,
         0,0,0,0,0,0,0,0});
    saveChar('[',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,1,0,0,
         0,0,1,0,0,0,0,0,
         0,0,1,0,0,0,0,0,
         0,0,1,0,0,0,0,0,
         0,0,1,0,0,0,0,0,
         0,0,1,1,1,1,0,0,
         0,0,0,0,0,0,0,0});
    saveChar(']',
        {0,0,0,0,0,0,0,0,
         0,0,1,1,1,1,0,0,
         0,0,0,0,0,1,0,0,
         0,0,0,0,0,1,0,0,
         0,0,0,0,0,1,0,0,
         0,0,0,0,0,1,0,0,
         0,0,1,1,1,1,0,0,
         0,0,0,0,0,0,0,0});
    saveChar('-',
        {0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         1,1,1,1,1,1,1,1,
         1,1,1,1,1,1,1,1,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0});
    saveChar('/',
        {0,0,0,0,0,0,0,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,1,1,1,0,
         0,0,0,1,1,0,0,0,
         0,0,0,1,1,0,0,0,
         0,1,1,1,0,0,0,0,
         0,1,1,0,0,0,0,0,
         0,0,0,0,0,0,0,0});
    saveChar('.',
        {0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,
         0,0,0,0,0,1,1,0,
         0,0,0,0,0,1,1,0});

    errorChar_ = fontMat({1,1,1,1,1,1,1,1,
                          1,0,0,0,0,0,0,1,
                          1,0,1,1,0,0,0,1,
                          1,0,1,1,1,0,0,1,
                          1,0,0,1,1,1,0,1,
                          1,0,1,0,1,1,0,1,
                          1,0,0,1,0,0,0,1,
                          1,1,1,1,1,1,1,1});
}

void InnerBmpFont::saveChar(char c, const fontMat& arr) {
    chars_[c] = arr;
}

void InnerBmpFont::Render(const std::string& str,
                          int pt,
                          const Point& pos,
                          const Color& color) {
    for (size_t i = 0; i < str.length(); i++) {
        Point p = pos;
        p.x += pt * i;
        RenderChar(str[i], pt, p, color);
    }
}

void InnerBmpFont::RenderChar(int ch,
                              int pt,
                              const Point& pos,
                              const Color& color) {
    if (ch == ' ')
        return;
    auto it = chars_.find(ch);
    if (it != chars_.end()) {
        renderChar(it->second, pt, pos, color);
    } else {
        renderChar(errorChar_, pt, pos, color);
    }
}

void InnerBmpFont::renderChar(const fontMat& data,
                              int pt,
                              const Point& pos,
                              const Color& color) {
    int len = std::ceil(pt / FontWidth);
    Rect tileRect = Rect{0, 0, float(len), float(len)};
    Renderer::SetDrawColor(color);
    for (size_t i = 0; i < data.size(); i++) {
        if (data[i]) {
            Point p;
            p.x = i % FontWidth;
            p.y = i / FontWidth;
            tileRect.x = tileRect.w * p.x + pos.x;
            tileRect.y = tileRect.h * p.y + pos.y;
            Renderer::FillRect(tileRect);
        }
    }
}

bool InnerBmpFont::HasChar(int ch) {
    return chars_.find(ch) != chars_.end();
}
